package cn.jdemo.guava.caffeine;

import com.github.benmanes.caffeine.cache.*;

import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @see Caffeine
 *
 * @see Cache 手动加载
 * @see LoadingCache 同步加载
 * @see AsyncLoadingCache 异步加载
 * 
 * @see Caffeine#expireAfterAccess(Duration) 一直有请求访问该key，那么这个缓存将一直不会过期。
 * @see Caffeine#expireAfterWrite(Duration) 在最后一次写入缓存后开始计时，在指定的时间后过期
 * @see Caffeine#expireAfter(Expiry) : 自定义策略，过期时间由Expiry实现独自计算
 *
 * @see Caffeine#refreshAfterWrite(Duration): 经固定的时间间隔，刷新缓存
 * @see CacheLoader#reload(Object, Object)  二者配合使用
 */
public class Demo01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /*test01();
        test02();*/
        test03();
    }

    /**
     * 手动加载-get key的时候指定一个同步的函数，如果key不存在就调用这个函数生成一个值
     */
    private static void test01() {
        Cache<String, String> cache = Caffeine.newBuilder()
                .initialCapacity(128)//初始大小
                .maximumSize(10 * 1000)//最大数量
                .expireAfterWrite(60, TimeUnit.SECONDS)//过期时间
                .build();

        System.out.println(cache.get("key1",t->{
            return t+ "value";
        }));
    }

    /**
     * 同步加载-build方法传入一个CacheLoader实现类。实现load方法，通过key加载value
     */
    private static void test02() {
        LoadingCache<String, String> cache = Caffeine.newBuilder()
                .initialCapacity(128)//初始大小
                .maximumSize(10 * 1000)//最大数量
                .expireAfterWrite(60, TimeUnit.SECONDS)//过期时间
                .refreshAfterWrite(1, TimeUnit.MINUTES)
                .build(key->{
                    return key+"value";
                });

        System.out.println(cache.get("随便"));
    }

    /**
     * 异步加载
     */
    private static void test03() throws ExecutionException, InterruptedException {
        AsyncLoadingCache<String, String> cache = Caffeine.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(1, TimeUnit.MINUTES)
                .buildAsync(key -> {return key+"value";});
        CompletableFuture<String> future = cache.get("随便");
        System.out.println(future.get());
    }
}
